package processer

import (
	"communication-system/common/messages"
	"communication-system/common/utils"
	"communication-system/server/model"
	"encoding/json"
	"fmt"
	"net"
)

//定义一个用于处理登录业务的结构体
type UserProcess struct {
	Conn   net.Conn
	UserId int
}

//编写一个用于后端server真正处理登录相关的业务逻辑函数
func (userprocess *UserProcess) ServerProcessLogin(mes *messages.Message) (err error) {

	//1.先从客户端发来的消息体mes中取出mes.data（此时是序列化之后的数据），并直接反序列化成对应的结构体
	var loginmes messages.LoginMess
	err = json.Unmarshal([]byte(mes.Data), &loginmes)
	if err != nil {
		fmt.Println("loginmes反序列化失败,err=", err)
		return
	}
	//声明一个返回给客户端的响应结果数据类型
	var loginresmess messages.Message
	loginresmess.Type = messages.LoginResMessType
	//声明一个返回登录类型的消息实例对象
	var loginresmessData messages.LoginResMess
	//此处我们需要与redis交互去验证登录信息

	res, err := model.MyUserDao.Login(loginmes.UserId, loginmes.UserPwd)
	if err != nil {

		if err == model.ErrOR_USER_NOTEXISTS {
			loginresmessData.Code = 500
			loginresmessData.Error = err.Error()
		} else if err == model.ErrOR_USER_PWD {
			loginresmessData.Code = 403
			loginresmessData.Error = err.Error()
		} else {
			loginresmessData.Code = 505
			loginresmessData.Error = "服务器内部错误...."
		}

	} else {
		loginresmessData.Code = 200
		userprocess.UserId = loginmes.UserId
		usermger.AddOnlineUsers(userprocess)
		fmt.Printf("用户:%v经过对比登录成功\n", res)
		//通知其他用户我上线了
		userprocess.NotifyOthersOnlineUser(loginmes.UserId)

		//将所有在线的用户id存放在LoginResMess.UserIds中、
		for id, _ := range usermger.onlineusers {
			loginresmessData.UserIds = append(loginresmessData.UserIds, id)
		}
	}

	//将loginresmessData序列化，并封装给messages.Message便于返回
	data, err := json.Marshal(loginresmessData)
	if err != nil {
		fmt.Println("将loginresmessData序列化,序列化失败,err=", err)
		return
	}
	loginresmess.Data = string(data)
	fmt.Println("登录成功后的loginresmess消息体:", loginresmess)
	//将loginresmess序列化，发送给客户端
	data, err = json.Marshal(loginresmess)
	if err != nil {
		fmt.Println("loginresmess序列化失败..,err=", err)
		return
	}
	//返回结果数据给客户端
	transfer := &utils.TransFer{
		Conn: userprocess.Conn,
	}
	err = transfer.WritePkg(data)
	if err != nil {
		fmt.Println("loginresmess序列化后返回给前端失败")
		return
	}

	return
}

//编写一个用于后端server真正处理注册相关的业务逻辑函数
func (userprocess *UserProcess) ServerProcessRegister(mes *messages.Message) (err error) {

	//1.先从客户端发来的消息体mes中取出mes.data（此时是序列化之后的数据），并直接反序列化成对应的结构体
	var Registermes messages.RegisterMess
	fmt.Println("获取前端传来的mes.data:", mes.Data)
	err = json.Unmarshal([]byte(mes.Data), &Registermes.User)
	if err != nil {
		fmt.Println("Registermes反序列化失败,err=", err)
		return
	}
	fmt.Println("Registermes的数据:", Registermes.User)
	fmt.Printf("Registermes.User.UserId:%v", Registermes.User.UserId)
	//声明一个返回给客户端的响应结果数据类型
	var registresmess messages.Message
	registresmess.Type = messages.RegisterResMessType
	//声明一个返回登录类型的消息实例对象
	var RegistresmessData messages.RegisterResMess
	//此处我们需要与redis交互去验证登录信息

	err = model.MyUserDao.Register(&Registermes.User)
	if err != nil {

		if err == model.ErrOR_USER_EXISTS {
			RegistresmessData.Code = 505
			RegistresmessData.Error = err.Error()
		} else {
			RegistresmessData.Code = 506
			RegistresmessData.Error = "服务器内部发生未知错误...."
		}

	} else {
		RegistresmessData.Code = 200

	}

	//将RegistresmessData序列化，并封装给messages.Message便于返回
	data, err := json.Marshal(RegistresmessData)
	if err != nil {
		fmt.Println("将RegistresmessData序列化,序列化失败,err=", err)
		return
	}
	registresmess.Data = string(data)
	fmt.Println("注册成功后的registresmess消息体:", registresmess)
	//将registresmess序列化，发送给客户端
	data, err = json.Marshal(registresmess)
	if err != nil {
		fmt.Println("registresmess序列化失败..,err=", err)
		return
	}
	//返回结果数据给客户端
	transfer := &utils.TransFer{
		Conn: userprocess.Conn,
	}
	err = transfer.WritePkg(data)
	if err != nil {
		fmt.Println("registresmess序列化后返回给前端失败")
		return
	}

	return
}

//通知所有在线用户的方法，登录成功后通知其他用户我已上线
func (userprocess *UserProcess) NotifyOthersOnlineUser(userid int) {
	//遍历onlineUsers,取出在线的其他用户，然后一个一个的给其他用户发送NotifyUserStatusMes
	for id, up := range usermger.onlineusers { //up就是取出的其他用户
		if id == userid {
			continue
		}
		//开始通知其他用户我上线了，userid是传的我的id

		up.NotifyMeOnline(userid)
	}

}

func (userprocess *UserProcess) NotifyMeOnline(userid int) {

	//组装返回给client的NotifyUserStatusMes消息体
	var mes messages.Message
	mes.Type = messages.NotifyUserStatusMesType
	var notifyUserStatusMes messages.NotifyUserStatusMes
	notifyUserStatusMes.UserId = userid
	notifyUserStatusMes.UserStatus = messages.UserOnline
	

	//序列化消息
	data,err:=json.Marshal(notifyUserStatusMes)
	if err != nil {
		fmt.Println("notifyUserStatusMes序列化失败...",err)
		return
	}
	//将序列化后的data赋值给mes.data
	mes.Data=string(data)
	//将mes.data序列化，等待发送给客户端
	data,err =json.Marshal(mes)
	if err != nil {
		fmt.Println("mes序列化失败...",err)
		return
	}
	//发送给客户端
	tf :=&utils.TransFer{
		Conn: userprocess.Conn,
	}
	err =tf.WritePkg(data)
	if err != nil {
		fmt.Println("发送客户端用户状态失败...",err)
		return
	}


}
